package com.hzw.saas.service.group.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.group.IGroupRoleService;
import com.hzw.saas.api.group.bo.GroupPermissionBo;
import com.hzw.saas.api.group.bo.GroupRoleBo;
import com.hzw.saas.api.group.bo.GroupRolePermBo;
import com.hzw.saas.api.group.query.GroupRoleQuery;
import com.hzw.saas.api.group.query.GroupRoleUQuery;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.common.util.IdWorker;
import com.hzw.saas.service.group.mapper.GroupPermissionMapper;
import com.hzw.saas.service.group.mapper.GroupRoleMapper;
import com.hzw.saas.service.group.mapper.GroupRolePermRefMapper;
import com.hzw.saas.service.group.model.GroupPermission;
import com.hzw.saas.service.group.model.GroupRole;
import com.hzw.saas.service.group.model.GroupRolePermRef;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import jodd.util.StringUtil;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;

/**
 * <p>
 * 群组角色表 服务实现类
 * </p>
 *
 * @author sonam
 * @since 2020-12-23
 */
@AllArgsConstructor
@Service("groupRoleServiceImpl")
public class GroupRoleServiceImpl extends ServiceImpl<GroupRoleMapper, GroupRole> implements IGroupRoleService, IService<GroupRole> {

    private final GroupRolePermRefMapper rolePermRefMapper;
    private final GroupPermissionMapper permissionMapper;
    private final MapperFacade mapperFacade;
    private final IdWorker idWorker;

    @Override
    public boolean existRole(String roleName) {
        return count(Wrappers.<GroupRole>lambdaQuery().eq(GroupRole::getRoleName, roleName)) > 0;
    }

    private void checkPerm(List<String> permIds) {
        Integer count = permissionMapper.selectCount(Wrappers.<GroupPermission>lambdaQuery()
            .in(GroupPermission::getPermId, permIds));

        AssertUtil.assertThrow("添加角色失败，设置的权限模块不存在", !Objects.equals(count, permIds.size()));
    }

    @Override
    @Transactional
    public GroupRolePermBo addRole(GroupRoleQuery roleParam) {

        AssertUtil.assertThrow("角色存在", existRole(roleParam.getRoleName()));

        String roleId = String.valueOf(idWorker.nextId());
        if(CollectionUtils.isNotEmpty(roleParam.getPermIds())) {
            // 判断权限id是否符合条件
            checkPerm(roleParam.getPermIds());
            // 添加权限到角色(//TODO 改为批量插入)
            roleParam.getPermIds().forEach(permId -> {
                GroupRolePermRef rolePermRef = new GroupRolePermRef();
                rolePermRef.setRoleId(roleId);
                rolePermRef.setPermId(permId);
                rolePermRefMapper.insert(rolePermRef);
            });
        }

        GroupRole role = new GroupRole();
        role.setRoleId(roleId);
        role.setRoleName(roleParam.getRoleName());
        this.save(role);

        GroupRolePermBo roleDto = mapperFacade.map(role, GroupRolePermBo.class);
        return roleDto;
    }

    @Override
    public IPage<GroupRoleBo> getRoleListByPage(IPage pageParam) {
        return this.page(pageParam, Wrappers.<GroupRole>lambdaQuery().orderByDesc(GroupRole::getCreateDate));
    }

    @Override
    @Transactional
    public boolean removeBatch(String[] roleIds) {
        /** 查看是否包含默认角色*/
        AssertUtil.assertThrow("默认角色不能删除",
            this.count(Wrappers.<GroupRole>lambdaQuery().in(GroupRole::getRoleId, roleIds)
                .eq(GroupRole::getIsDefault, true)) > 0);

        // 删除关联表
        rolePermRefMapper.delete(Wrappers.<GroupRolePermRef>lambdaQuery()
            .in(GroupRolePermRef::getRoleId, roleIds));

        // TODO 删除用户与角色之间的关联

        return this.removeByIds(Arrays.asList(roleIds));
    }

    @Override
    public GroupRolePermBo getRoleById(String roleId) {
        GroupRolePermBo roleDto = mapperFacade.map(this.getById(roleId), GroupRolePermBo.class);

        List<GroupRolePermRef> rolePermRefs = rolePermRefMapper.selectList(Wrappers.<GroupRolePermRef>lambdaQuery()
            .select(GroupRolePermRef::getPermId)
            .eq(GroupRolePermRef::getRoleId, roleId));

        if(CollectionUtils.isNotEmpty(rolePermRefs)) {
            List<String> permIds = new ArrayList<>();
            rolePermRefs.forEach(rolePermRef -> {
                permIds.add(rolePermRef.getPermId());
            });

            List<GroupPermission> permissionList = permissionMapper.selectList(Wrappers.<GroupPermission>lambdaQuery()
                .in(GroupPermission::getPermId, permIds));

            List<GroupPermissionBo> permissionDtoList = mapperFacade.mapAsList(permissionList, GroupPermissionBo.class);
            roleDto.setPermissionDtoList(permissionDtoList);
        }

        return roleDto;
    }

    @Override
    @Transactional
    public void updateRole(GroupRoleUQuery roleUParam) {
        GroupRole role = mapperFacade.map(roleUParam, GroupRole.class);
        /** 更新角色名称 */
        if((StringUtil.isNotBlank(roleUParam.getRoleName()) ||
            roleUParam.getIsDefault() != null) &&
            existRole(roleUParam.getRoleName())) {
            this.updateById(role);
        }
        /** 更新角色权限*/
        // 先删除角色权限关联
        rolePermRefMapper.delete(Wrappers.<GroupRolePermRef>lambdaQuery()
            .eq(GroupRolePermRef::getRoleId, role.getRoleId()));
        // 插入新的关联关系
        if(CollectionUtils.isNotEmpty(roleUParam.getPermIds())) {
            // 验证权限是否存在
            checkPerm(roleUParam.getPermIds());
            // 权限和角色关联
            roleUParam.getPermIds().forEach(permId -> {
                GroupRolePermRef permRef = new GroupRolePermRef();
                permRef.setRoleId(role.getRoleId());
                permRef.setPermId(permId);
                rolePermRefMapper.insert(permRef);
            });
        }

    }

}
